import Events
from Weapon import *
from direct.showbase.Loader import Loader
from direct.task import Task 
from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay
from panda3d.core import Filename,AmbientLight,DirectionalLight
from panda3d.core import PandaNode,NodePath,Camera,TextNode
from panda3d.core import Vec3,Vec4,BitMask32,Point3,VBase4
from direct.gui.OnscreenText import OnscreenText
#temp
from panda3d.physics import BaseParticleEmitter,BaseParticleRenderer
from panda3d.physics import PointParticleFactory,SpriteParticleRenderer
from panda3d.physics import LinearNoiseForce,DiscEmitter
from direct.particles.Particles import Particles
from direct.particles.ParticleEffect import ParticleEffect

from direct.actor.Actor import Actor
import random, sys, os, math

class Events():
     def __init__(self,base):
        funcMap = {"sys.exit":base.Gui.button,"self.OnceButton":self.OnceButton,"self.setKey": self.setKey,"self.setMbutton": self.setMbutton,
        "self.toggledebug":self.toggledebug,"self.togglewireframe":self.togglewireframe,"self.togglelighting":self.togglelighting,"self.toggletextures":self.toggletexture,
        "self.noclip":self.noclip}

        self.keyMap = {"A":0, "D":0, "W":0, "S":0,"space":0,"ctrl":0,"G":0,"R":0,"B":0,"K":0,"P":0}
        self.mousemap = {"m1":0,"m2":0,"m3":0}
        f = open("controls.xml", "r")
        text = f.readlines()
        for n in range(len(text)):
            newline = str(text[n]).replace("\n","").split(",")
            if len(newline) == 4:
                list = [newline[2],int(newline[3])]
                f = funcMap[newline[1]]
                base.accept(newline[0],f,list)
            elif len(newline) == 2:
                f = funcMap[newline[1]]
                base.accept(newline[0],f)
            elif len(newline) == 5:
                f = funcMap[newline[1]]
                base.acceptonce(newline[0],f)
        base.accept("v", base.bufferViewer.toggleEnable)
        base.accept("V", base.bufferViewer.toggleEnable)
        base.bufferViewer.setPosition("llcorner")
        base.accept('physx-trigger-enter', self.doEnter)
        base.accept('physx-trigger-stay',  self.doStay)
        base.accept('physx-trigger-leave', self.doLeave)
        #base.accept('physx-controller-down',self.doDown)
        base.accept("window-event", self.WindowEvent)

     def handleEventGame(self,task):
        player = base.Player1
        base.watermesh.setShaderInput('eyePositionW',base.camera.getPos(render))
        base.watermesh.setShaderInput('param1',1.0,0.8,globalClock.getFrameTime(),-globalClock.getFrameTime())
        base.rig.setPos(base.camera.getPos(render))
        if base.buffer.isActive():
            base.buffer.setActive(0)
        base.dlnp.lookAt(0,30,0)
#        base.dlnp.posInterval(0.1,lightpos)
        playergun = player.gunlist[player.equip[player.current]]
        forward = Vec3(player.dummy.getMat().getRow3(1))
        side = Vec3(player.dummy.getMat().getRow3(0))
        bodyForward = base.Physics1.controller.getActor().getGlobalMat().rotateMat(player.dummy.getH(),Vec3(0,0,1)).getRow3(1)
        bodySide = base.Physics1.controller.getActor().getGlobalMat().rotateMat(player.dummy.getH(),Vec3(0,0,1)).getRow3(0)
        if player.isNocliping:
            bodyForward = forward
        if base.Player1.onLadder == 1:
            base.Physics1.controller.stop_jump()
            if forward[2] >= -0.2:
                bodyForward = Vec3(0,0,1)
            else:
                bodyForward = Vec3(0,0,-1)
        if (self.keyMap["space"]!=0):
            if not player.isNocliping:
                if player.onLadder == 0:
                    base.Physics1.doJump()
            
#        if (self.keyMap["ctrl"]!=0):
#            if not base.Physics1.crouching:
#                base.Physics1.crouching = True
#                base.Physics1.doCrouch()
#        else:
#            if base.Physics1.crouching:
#                base.Physics1.crouching = False
#                base.Physics1.unCrouch()
        force = 0
        strafe = 0
        time = int(base.client.remainTime)
        m = 0
        s = 0
        while time > 0:
            if time > 59:
                m+=1
                time-=60
            else:
                s= time
                if s < 10:
                    s = "0"+str(s)
                break
        timeSTR = str(m)+" : "+str(s)
        base.Gui.GuiTimeWord.setText(timeSTR)
        base.Gui.GuiHPWord.setText(str(player.hp))
        if player.hp <= 0:
            player.ownmodel.hide()
            base.Gui.GuiHPWord.hide()
        else:
            player.ownmodel.show()
            base.Gui.GuiHPWord.show()
        if (self.keyMap["W"]!=0):
            force = base.Cam1.movespeed
        if (self.keyMap["S"]!=0):
            force = -base.Cam1.movespeed
        if (self.keyMap["A"]!=0):
            strafe = -base.Cam1.movespeed
        if (self.keyMap["D"]!=0):
            strafe = base.Cam1.movespeed
        if (self.keyMap["R"]!=0):
            base.r+=0.0001
            print base.r
        if (self.keyMap["G"]!=0):
            base.g+=0.0001
            print base.g
        if (self.keyMap["B"]!=0):
            base.b+=0.0001
            print base.b

        #-----------------MOUSE----------------#
        if player.hp > 0:
            if self.mousemap["m1"]!=0:
                player.gunlist[player.equip[player.current]].Fire()
            elif self.mousemap["m1"]== 0 and player.gunlist[player.equip[player.current]].automatic == False:
                 player.gunlist[player.equip[player.current]].canfire = True
        #if self.mousemap["m2"]!=0:
       # if self.mousemap["m3"]!=0:
        if not base.pause:
            if base.mouseWatcherNode.hasMouse():
                try:
                      x=base.mouseWatcherNode.getMouseX()
                      y=base.mouseWatcherNode.getMouseY()
                      move = [x,y]
                      base.Cam1.heading -= move[0]*base.Cam1.sensitivity
                      base.Cam1.pitch += move[1]*base.Cam1.sensitivity
                      base.win.movePointer(0, base.Centre[0], base.Centre[1])
                      base.Cam1.Update()
                except:
                      print "Unexpected error:", sys.exc_info()[0]
        dir = (Vec3(bodyForward)*force + Vec3(bodySide)*strafe)
        base.Physics1.controller.setLocalSpeed(dir)
        time = globalClock.getFrameTime()
        if time - playergun.lastfired >= 0.05:
            playergun.offset = playergun.baseoffset
        #base.skydome.setPos(player.dummy.getPos())
        return Task.cont

     def setKey(self, key, value):
        self.keyMap[key] = value
        
     def setMbutton(self,button,value):
         self.mousemap[button] = value
         
     def toggledebug(self):
        # base.setSceneGraphAnalyzerMeter(True)
         render.analyze()
            #base.setSceneGraphAnalyzerMeter(True)

     def togglewireframe(self):
        base.toggleWireframe()

     def togglelighting(self):
        if not base.lighting:
            base.buffer.setActive(0)
            base.lighting = True
        else:
            base.buffer.setActive(1)
            base.lighting = False

     def toggletexture(self):
        base.toggleTexture()

     def IsInView(self, object):
       lensBounds = base.cam.node().getLens().makeBounds()
       bounds = object.getBounds()
       bounds.xform(object.getParent().getMat(base.cam))
       return lensBounds.contains(bounds)

     def noclip(self):
        if base.Player1.isNocliping == 0:
           # base.Player1.onLadder = 1
            base.Cam1.movespeed = 30
            base.Physics1.controller.set_gravity(Vec3(0,0,0))
            base.Physics1.controller.getActor().setActorFlag(1,True)
            base.Player1.isNocliping = 1
        else:
           # base.Player1.onLadder = 0
            base.Cam1.movespeed = 10
            base.Physics1.controller.set_gravity(Vec3(0,0,1))
            base.Physics1.controller.getActor().setActorFlag(1,False)
            base.Player1.isNocliping = 0
     def findCenter(self):
       winX = base.props.getXSize()
       winY = base.props.getYSize()
       return [winX / 2, winY / 2]

     def OnceButton(self,key,value):
         if key == "Q":
            i = base.Player1.lastwep
            base.Player1.lastwep = base.Player1.current
            base.Player1.current = i
            base.Player1.SetModel()
         if key == "1":
            if base.Player1.current != 0:
                base.Player1.lastwep = base.Player1.current
                base.Player1.current = 0
                base.Player1.SetModel()
         if key == "2":
            if base.Player1.current != 1:
                base.Player1.lastwep = base.Player1.current
                base.Player1.current = 1
                base.Player1.SetModel()
         if key == "3":
            if base.Player1.current != 2:
                base.Player1.lastwep = base.Player1.current
                base.Player1.current = 2
                base.Player1.SetModel()
     def WindowEvent(self,a=0):
        width = base.win.getProperties().getXSize()
        height = base.win.getProperties().getYSize()
        base.Centre = [width/2,height/2]
        base.cam.node().getLens().setFilmSize(width, height)
       # base.cam.node().getLens().setFocalLength(1000)
         
     def doEnter(self, triggerShape, otherShape):
        name1 = triggerShape.getActor().getName()
        name2 = otherShape.getActor().getName()
        if "Ladder" in name1:
            if "Player" in name2:
                base.Player1.onLadder = 1
                base.Physics1.controller.set_gravity(Vec3(0,0,0))

     def doStay(self, triggerShape, otherShape):
        name1 = triggerShape.getActor().getName()
        name2 = otherShape.getActor().getName()

     def doLeave(self, triggerShape, otherShape):
        name1 = triggerShape.getActor().getName()
        name2 = otherShape.getActor().getName()
        if "Ladder" in name1:
            if "Player" in name2:
                base.Player1.onLadder = 0
                base.Physics1.controller.set_gravity(Vec3(0,0,1))
     def doDown(self, *args):
            print 'DOWN:', args